package com.chebaohui.iqs.service.impl.deal.taiping.profess;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chebaohui.iqs.config.CompanyValue;
import com.chebaohui.iqs.config.InsuranceCode;
import com.chebaohui.iqs.config.ResultCode;
import com.chebaohui.iqs.entity.base.CarOrder;
import com.chebaohui.iqs.entity.base.Insurance;
import com.chebaohui.iqs.entity.req.CarPrice;
import com.chebaohui.iqs.entity.res.CompanyCarPrice;
import com.chebaohui.iqs.sdk.chaojiying.ChaoJiYingSdk;
import com.chebaohui.iqs.service.impl.deal.taiping.ResTaiPing;
import com.chebaohui.iqs.service.impl.deal.taiping.ev.E03Request;
import com.chebaohui.iqs.service.impl.deal.taiping.ev.E04Request;
import com.chebaohui.iqs.service.impl.deal.taiping.ev.V02Request;
import com.chebaohui.iqs.service.impl.deal.util.StringUtil;
import com.chebaohui.iqs.service.impl.deal.util.TimeBase;

/**
 * 太平车险算费
 * 
 * @author regas_xie
 *
 */
public class TpCarPrice {
	/**
	 * log:日志输出
	 */
	private Log log = LogFactory.getLog(TpCarPrice.class);

	private CarPrice param;// 请求参数
	private CompanyCarPrice result;// 返回结果
	private String session = "";// 接口session
	private int intMax = 2;// 识码调用次数
	private JSONObject price;// 报价接口参数

	/**
	 * @param param
	 *            报价参数
	 * @param code
	 *            保险公司编码
	 * @param carCode
	 *            车型编码
	 */
	public TpCarPrice(CarPrice param, String code, String carCode) {
		result = new CompanyCarPrice();
		price = new JSONObject();
		result.setCompanyCode(code);// 保险公司编码
		result.setModelCode(carCode);// 车型编码
		this.param = param;
	}

	/**
	 * 太平直连接口V02方式<自选>报价
	 * 
	 * @return
	 */
	public CompanyCarPrice priceV02() {
		try {
			price.put("orderNo", getOrderNo());// 设置订单号
			setRequestTP();// 设置车险列表

			ResTaiPing v02 = V02Request.requestV02(session, price);// V02自选车险算费
			log.info(param.getLicense().getLicenceNo() + "-v02:" + "\n" + v02.getMsg());
			if (!v02.isState()) {
				result.setCode(v02.getError().getCode());
				result.setMsg(v02.getError().getMsg() + (StringUtil.isNulls(v02.getErrMsg()) ? "" : v02.getErrMsg()));
				return result;
			}

			JSONArray versionsUnifyCheck = null;
			for (int s = 1; s <= intMax; s++) {
				versionsUnifyCheck = v02.getResult().getJSONArray("versionsUnifyCheck");
				if (null != versionsUnifyCheck && !versionsUnifyCheck.isEmpty()) {// 有验证码，需要验证码图片识别或报错返回
					setCheckQuestion(versionsUnifyCheck);
					session = v02.getHead().getString("session");
					v02 = V02Request.requestV02(session, price);// V02自选车险算费---再次报价
					log.info(param.getLicense().getLicenceNo() + "-v02(识码第" + s + "次后):" + "\n" + v02.getMsg());
					if (!v02.isState()) {
						result.setCode(v02.getError().getCode());
						result.setMsg(
								v02.getError().getMsg() + (StringUtil.isNulls(v02.getErrMsg()) ? "" : v02.getErrMsg()));
						return result;
					}
					continue;
				} else
					break;
			}

			if (null != versionsUnifyCheck && !versionsUnifyCheck.isEmpty()) {// 有验证码，需要验证码图片识别
				result.setCode(ResultCode.N02.getCode());
				result.setMsg(ResultCode.N02.getMsg() + "验证码无法用工具识别");
				return result;
			}

			setResponse(v02.getResult());
			// 取报价数据
			return result;
		} catch (Exception e) {
			log.error(param.getLicense().getLicenceNo() + ":" + e.getMessage());
			return error(e.getMessage());
		}
	}

	/**
	 * 太平车险算费后返回数据设置
	 * 
	 * @throws Exception
	 */
	private void setResponse(JSONObject res) throws Exception {
		try {
			result.setCode(ResultCode.SUCCESS.getCode());
			result.setMsg(ResultCode.SUCCESS.getMsg());

			CarOrder carOrder = new CarOrder();
			List<Insurance> insuranceList = new ArrayList<>();
			BigDecimal total = new BigDecimal("0.00");
			BigDecimal busTotal = new BigDecimal("0.00");
			carOrder.setOrederNo(price.getString("orderNo"));
			carOrder.setDutyFree("2");
			if (!tra) {
				carOrder.setTraNo(price.getString("orderNo"));
				carOrder.setTraRenewal("2");
				carOrder.setTraBeginTime(getResTime(res.getJSONArray("risk"), "BZ"));
				carOrder.setTraEndTime(TimeBase.getNextYear(carOrder.getTraBeginTime(), "yyyy-MM-dd HH:mm:ss"));
				carOrder.setTraPrice(res.getJSONArray("itemKindBZ").getJSONObject(0).getString("priceTaxTotal"));
				total = total.add(new BigDecimal(carOrder.getTraPrice()));
				carOrder.setTaxPrice(res.getJSONArray("tax").getJSONObject(0).getString("sumPayTax"));
				total = total.add(new BigDecimal(carOrder.getTaxPrice()));
				insuranceList.add(getResInsView(InsuranceCode.TP, carOrder.getTraPrice(), null, "", "", ""));
			}
			if (!bus) {
				carOrder.setBusNo(price.getString("orderNo"));
				carOrder.setBusRenewal("2");
				carOrder.setBusBeginTime(getResTime(res.getJSONArray("risk"), "BS"));
				carOrder.setBusEndTime(TimeBase.getNextYear(carOrder.getBusEndTime(), "yyyy-MM-dd HH:mm:ss"));
				JSONArray itemKindBS = res.getJSONArray("itemKindBS");
				JSONArray zhu = new JSONArray();
				JSONArray chi = new JSONArray();
				for (int i = 0; i < itemKindBS.size(); i++) {
					busTotal = busTotal.add(new BigDecimal(itemKindBS.getJSONObject(i).getString("priceTaxTotal")));
					int check = getResInsZhu(itemKindBS.getJSONObject(i).getString("kindCode"));
					if (check == 1)
						zhu.add(itemKindBS.getJSONObject(i));
					else if (check == 2)
						chi.add(itemKindBS.getJSONObject(i));
					else {
						throw new Exception("太平车险算费后返回数据设置错误:车险错误。" + itemKindBS.getJSONObject(i));
					}
				}

				for (int i = 0; i < zhu.size(); i++) {
					insuranceList.add(getInsZhu(zhu.getJSONObject(i), chi));
				}
			}

			total = total.add(busTotal);
			carOrder.setBusTotalPrice(busTotal.toString());
			carOrder.setTotalCarPrice(total.toString());
			result.setCarOrder(carOrder);
			result.setInsuranceList(insuranceList);
		} catch (Exception e) {
			throw new Exception("太平车险算费后返回数据设置异常:" + e.getMessage());
		}
	}

	/**
	 * 车险分类
	 * 
	 * @param code
	 * @return
	 */
	private int getResInsZhu(String code) {
		String[] list = { "01", "03", "02", "041", "044", "11", "13", "21" };
		for (String i : list) {
			if (i.equals(code))
				return 1;
		}

		String[] lists = { "601", "603", "602", "604", "61" };
		for (String i : lists) {
			if (i.equals(code))
				return 2;
		}

		return 3;
	}

	/**
	 * 不计免赔 --详情获取
	 * 
	 * @param code
	 * @param chi
	 * @return
	 */
	private JSONObject getInsChi(String code, JSONArray chi) {
		for (int i = 0; i < chi.size(); i++) {
			if (code.equals(chi.getJSONObject(i).getString("kindCode"))) {
				return chi.getJSONObject(i);
			}
		}
		return null;
	}

	/**
	 * 商业险详情获取
	 * 
	 * @param res
	 * @param chi
	 * @return
	 * @throws Exception
	 */
	private Insurance getInsZhu(JSONObject res, JSONArray chi) throws Exception {
		if ("01".equals(res.getString("kindCode"))) {// 机动车损失保险
			JSONObject c = getInsChi("601", chi);// 车损不计免
			return getResInsView(InsuranceCode.BL, res.getString("priceTaxTotal"),
					null == c ? null : c.getString("priceTaxTotal"), res.getString("sumInsured"), "", "");
		} else if ("03".equals(res.getString("kindCode"))) {// 全车盗抢保险
			JSONObject c = getInsChi("603", chi);// 盗抢不计免
			return getResInsView(InsuranceCode.BT, res.getString("priceTaxTotal"),
					null == c ? null : c.getString("priceTaxTotal"), res.getString("sumInsured"), "", "");
		} else if ("02".equals(res.getString("kindCode"))) {// 第三者责任保险
			JSONObject c = getInsChi("602", chi);// 商三不计免
			return getResInsView(InsuranceCode.BTR, res.getString("priceTaxTotal"),
					null == c ? null : c.getString("priceTaxTotal"), res.getString("sumInsured"), "", "");
		} else if ("041".equals(res.getString("kindCode"))) {// 车上人员责任保险（司机）
			String price = "";
			if (getReqInsChi(InsuranceCode.BD)) {
				JSONObject c = getInsChi("604", chi);// 人员不计免
				if (null != c) {
					BigDecimal p = new BigDecimal(c.getString("priceTaxTotal"));
					price = p.divide(new BigDecimal("" + person), 2).toString();
				}
			}
			return getResInsView(InsuranceCode.BD, res.getString("priceTaxTotal"), price, res.getString("sumInsured"),
					"", "");
		} else if ("044".equals(res.getString("kindCode"))) {// 车上人员责任保险（乘客）
			String price = "";
			if (getReqInsChi(InsuranceCode.BP)) {
				JSONObject c = getInsChi("604", chi);// 人员不计免
				if (null != c) {
					BigDecimal p = new BigDecimal(c.getString("priceTaxTotal"));
					price = p.divide(new BigDecimal("" + person), 2).toString();
				}
			}
			return getResInsView(InsuranceCode.BP, res.getString("priceTaxTotal"), price, res.getString("sumInsured"),
					"", "");
		} else if ("11".equals(res.getString("kindCode"))) {// 玻璃单独破碎险
			return getResInsView(InsuranceCode.BG, res.getString("priceTaxTotal"), null, res.getString("sumInsured"),
					"", getReqInsV(InsuranceCode.BG).getType());
		} else if ("13".equals(res.getString("kindCode"))) {// 自燃损失险
			String p = "";
			if (getReqInsChi(InsuranceCode.BNP)) {
				JSONObject c = getInsChi("61", chi);// 附加险不计免
				BigDecimal pr = new BigDecimal(c.getString("priceTaxTotal"));
				p = pr.divide(new BigDecimal("" + addI), 2).toString();
			}

			return getResInsView(InsuranceCode.BNP, res.getString("priceTaxTotal"), p, res.getString("sumInsured"), "",
					"");
		} else if ("21".equals(res.getString("kindCode"))) {// 车身划痕损失险
			return getResInsView(InsuranceCode.BN, res.getString("priceTaxTotal"), null, res.getString("sumInsured"),
					"", "");
		} else {
			throw new Exception("太平车险算费后返回数据设置错误:车险代码没在开发内。" + res);
		}
	}

	/**
	 * 判断请求车险有无不计免赔
	 * 
	 * @param ins
	 * @return
	 */
	private boolean getReqInsChi(InsuranceCode ins) {
		for (Insurance i : param.getInsuranceList()) {
			if (ins.getCode().equals(i.getCode())) {
				return i.getIndemnity().equals("true");
			}
		}
		return false;
	}

	/**
	 * 获取请求参数中指定险别
	 * 
	 * @param ins
	 * @return
	 */
	private Insurance getReqInsV(InsuranceCode ins) {
		for (Insurance i : param.getInsuranceList()) {
			if (ins.getCode().equals(i.getCode())) {
				return i;
			}
		}
		return null;
	}

	/**
	 * 获取详细列表
	 * 
	 * @param ic
	 *            车险编码
	 * @param pri
	 *            保费
	 * @param ind
	 *            不计免赔费用
	 * @param amount
	 *            保额
	 * @param pate
	 *            费率
	 * @param type
	 *            类型
	 * @return
	 */
	private Insurance getResInsView(InsuranceCode ic, String pri, String ind, String amount, String pate, String type) {
		Insurance ins = new Insurance();
		ins.setCode(ic.getCode());
		if (!StringUtil.isNulls(amount)) {
			ins.setAuount("0");
		} else
			ins.setAuount(amount);

		ins.setPate(pate);
		ins.setType(type);
		ins.setValue(ic.getValue());
		ins.setInsurancePrice(pri);
		if (!StringUtil.isNulls(ind)) {
			ins.setIndemnityPrice(ind);
			ins.setIndemnity("true");
		} else {
			ins.setIndemnity("false");
			ins.setIndemnityPrice("0");
		}

		return ins;
	}

	/**
	 * 获取起保时间
	 * 
	 * @param risk
	 *            返回车险详情列表
	 * @param code
	 *            车险代码
	 * @return 错误返回 false
	 */
	private String getResTime(JSONArray risk, String code) {
		if (null == risk || risk.isEmpty())
			return "false";
		for (int i = 0; i < risk.size(); i++) {
			if (risk.getJSONObject(i).getString("riskCode").equals(code))
				return risk.getJSONObject(i).getString("startDate");
		}
		return "false";
	}

	/**
	 * 验证码答案设置
	 * 
	 * @throws Exception
	 */
	private void setCheckQuestion(JSONArray question) throws Exception {
		try {
			JSONArray versionsUnifyCheck = new JSONArray();
			for (int j = 0; j < question.size(); j++) {
				JSONObject check = question.getJSONObject(j);
				if (!StringUtil.isNulls(check.getString("checkQuestion"))) {
					if ("BZ".equals(check.getString("riskCode").trim())) {
						Map<String, String> identify = ChaoJiYingSdk
								.identifyBase64Img(check.getString("checkQuestion"));
						if (!"true".equals(identify.get("state"))) {
							throw new Exception("太平车险验证码工具识别错误:交强,"+identify.get("msg"));
						}
						
						JSONObject tra = new JSONObject();
						tra.put("checkAnswer", identify.get("data"));
						tra.put("demandNo", check.getString("demandNo"));
						tra.put("riskCode", "BZ");
						versionsUnifyCheck.add(tra);
					} else if ("BS".equals(check.getString("riskCode").trim())) {
						Map<String, String> identify = ChaoJiYingSdk
								.identifyBase64Img(check.getString("checkQuestion"));
						if (!"true".equals(identify.get("state"))) {
							throw new Exception("太平车险验证码工具识别错误:商业,"+identify.get("msg"));
						}
						
						JSONObject bus = new JSONObject();
						bus.put("checkAnswer", identify.get("data"));
						bus.put("demandNo", check.getString("demandNo"));
						bus.put("riskCode", "BS");
						versionsUnifyCheck.add(bus);
					}
				}
			}

			price.put("versionsUnifyCheck", versionsUnifyCheck);
		} catch (Exception e) {
			throw new Exception("太平车险验证码设置异常:" + e.getMessage());
		}
	}

	private boolean tra = true;// 交强险
	private boolean bus = true;// 商业险

	/**
	 * 设置车险列表清单
	 * 
	 * @throws Exception
	 */
	private void setRequestTP() throws Exception {
		try {

			JSONArray bsList = new JSONArray();
			for (Insurance i : param.getInsuranceList()) {
				if (InsuranceCode.TP.getCode().equals(i.getCode())) {
					JSONObject bz = new JSONObject();
					bz.put("BZState", true);
					bz.put("BZtime", TimeBase.getDay("yyyy-MM-dd", CompanyValue.nextDay()));
					tra = false;
					price.put("BZ", bz);
					continue;
				} else if (InsuranceCode.BTR.getCode().equals(i.getCode())) {
					JSONObject bs = new JSONObject();
					bs.put("BSState", true);
					bs.put("BStime", TimeBase.getDay("yyyy-MM-dd", CompanyValue.nextDay()));
					bus = false;
					price.put("BS", bs);
					bsList.add(getBusIns("02", i.getAuount(), "true".equals(i.getIndemnity()) ? true : false, 4, ""));
					continue;
				} else if (InsuranceCode.BL.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("01", "0.0", "true".equals(i.getIndemnity()) ? true : false, 4, ""));
					continue;
				} else if (InsuranceCode.BT.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("03", "0.0", "true".equals(i.getIndemnity()) ? true : false, 4, ""));
					continue;
				} else if (InsuranceCode.BD.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("041", i.getAuount(), "true".equals(i.getIndemnity()) ? true : false, 1, ""));
					continue;
				} else if (InsuranceCode.BP.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("044", i.getAuount(), "true".equals(i.getIndemnity()) ? true : false, 1, ""));
					continue;
				} else if (InsuranceCode.BN.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("21", i.getAuount(), "true".equals(i.getIndemnity()) ? true : false, 2, ""));
					continue;
				} else if (InsuranceCode.BG.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("11", "0.0", false, 3, i.getType()));
					continue;
				} else if (InsuranceCode.BNP.getCode().equals(i.getCode())) {
					bsList.add(getBusIns("13", "0.0", "true".equals(i.getIndemnity()) ? true : false, 2, ""));
					continue;
				} else {
					continue;
				}
			}
			price.put("itemKindBS", bsList);
			if (tra) {
				JSONObject bz = new JSONObject();
				bz.put("BZState", false);
				price.put("BZ", bz);
			}
			if (bus) {
				JSONObject bs = new JSONObject();
				bs.put("BSState", false);
				price.put("BS", bs);
			}
		} catch (Exception e) {
			throw new Exception("太平车险险别设置异常:" + e.getMessage());
		}
	}

	private double person = 1.0;// 计算人员不计免赔
	private double addI = 1.0;// 计算附加险不计免赔

	/**
	 * 获取商业险列表清单
	 * 
	 * @param code
	 *            险别代码
	 * @param insured
	 *            保额
	 * @param relate
	 *            是否不计免赔
	 * @param add
	 *            业务字段《为了计算反回保费》
	 * @param type
	 *            玻璃等类型
	 * @return
	 */
	private JSONObject getBusIns(String code, String insured, boolean relate, int add, String type) {
		JSONObject bus = new JSONObject();
		bus.put("kindCode", code);// 险别代码
		bus.put("insured", insured);// 保额
		if (relate)
			bus.put("relatedInd", "1");
		else
			bus.put("relatedInd", "0");

		if (1 == add) {
			if (relate)
				person += 1.0;
		} else if (2 == add) {
			if (relate)
				addI += 1.0;
		} else if (3 == add) {
			if ("01".equals(type))
				bus.put("glassType", "2");// 玻璃险-类型，1国产；2进口
			else
				bus.put("glassType", "1");
		}
		return bus;
	}

	/**
	 * 错误返回
	 * 
	 * @param err
	 * @return
	 */
	private CompanyCarPrice error(String err) {
		if (StringUtil.isNulls(result.getCode())) {
			result.setCode(ResultCode.N02.getCode());
			result.setMsg(ResultCode.N02.getMsg() + err);
			log.error(param.getLicense().getLicenceNo() + ":" + err);
		}
		return result;
	}

	/**
	 * 获取订单号
	 * 
	 * @return
	 */
	private String getOrderNo() throws Exception {
//		ResTaiPing e05=E05Request.requestE05(session, param.getLicense().getLableNo());
//		log.info(param.getLicense().getLicenceNo() + "-e05:" + "\n" + e05.getMsg());
//		if (!e05.isState()) {
//			result.setCode(e05.getError().getCode());
//			result.setMsg(e05.getError().getMsg() + (StringUtil.isNulls(e05.getErrMsg()) ? "" : e05.getErrMsg()));
//			throw new Exception("获取订单号错误-e02接口错误");
//		}
//		session = e05.getHead().getString("session");
		
//		ResTaiPing e02 = E02Request.requestE02(session, param.getLicense().getLicenceNo());
//		log.info(param.getLicense().getLicenceNo() + "-e02:" + "\n" + e02.getMsg());
//		if (!e02.isState()) {
//			result.setCode(e02.getError().getCode());
//			result.setMsg(e02.getError().getMsg() + (StringUtil.isNulls(e02.getErrMsg()) ? "" : e02.getErrMsg()));
//			throw new Exception("获取订单号错误-e02接口错误");
//		}
//		session = e02.getHead().getString("session");
//		if ("1".equals(e02.getResult().getJSONArray("baseInfo").getJSONObject(0).getString("status")))
//			return getOrderNoE03();
//		else
			return getOrderNoE04();
	}

	/**
	 * 通过E03获取订单号<续保太平>
	 * 
	 * @return
	 * @throws Exception
	 */
	protected String getOrderNoE03() throws Exception {
		ResTaiPing e03 = E03Request.requestE03(session, "", param.getLicense().getLicenceNo(),
				param.getOwner().getIdCard());
		log.info(param.getLicense().getLicenceNo() + "-e03:" + "\n" + e03.getMsg());
		if (!e03.isState()) {
			result.setCode(e03.getError().getCode());
			result.setMsg(e03.getError().getMsg() + (StringUtil.isNulls(e03.getErrMsg()) ? "" : e03.getErrMsg()));
			throw new Exception("获取订单号错误-e03接口错误");
		}
		session = e03.getHead().getString("session");
		return e03.getResult().getJSONArray("order").getJSONObject(0).getString("orderNo");
	}

	/**
	 * 通过E04获取订单号<之前未在太平投保>
	 * 
	 * @return
	 * @throws Exception
	 */
	private String getOrderNoE04() throws Exception {
		ResTaiPing e04 = E04Request.requestE04(session, getOwner());
		log.info(param.getLicense().getLicenceNo() + "-e04:" + "\n" + e04.getMsg());
		if (!e04.isState()) {
			result.setCode(e04.getError().getCode());
			result.setMsg(e04.getError().getMsg() + (StringUtil.isNulls(e04.getErrMsg()) ? "" : e04.getErrMsg()));
			throw new Exception("获取订单号错误-e04接口错误");
		}
		session = e04.getHead().getString("session");
		return e04.getResult().getJSONArray("order").getJSONObject(0).getString("orderNo");
	}

	/**
	 * 车主信息
	 * 
	 * @param license
	 * @return
	 */
	private JSONObject getOwner() {
		JSONObject owner = new JSONObject();
		owner.put("name", param.getLicense().getOwnerName());// 车主名称--Y
		// owner.put("identifyNumber", getPara(p, "ownerIDcard"));// 车主身份证号

		owner.put("chgOwnerFlag", param.getLicense().getTransfer());// 是否过户车-00、非过户车，01投保过户
		if ("01".equals(param.getLicense().getTransfer()))
			owner.put("transferDate", param.getLicense().getTransferDate());// 过户日期-若是过户车，需传值；
		else
			owner.put("transferDate", "");// 过户日期-若是过户车，需传值；

		owner.put("licenseNo", param.getLicense().getLicenceNo());// 车牌号--Y
		owner.put("engineNo", param.getLicense().getEngineNo());// 发动机号--Y
		owner.put("frameNo", param.getLicense().getFrameNo());// 车架号
		owner.put("SingeinDate", param.getLicense().getRegisteredTime());// 登记日期--Y

		//owner.put("cityCode", "500000");
		owner.put("modelCode", result.getModelCode());// 精友车型编码

		return owner;
	}
}